/**
 * @file MainWindow.cpp
 *
 * Implementation of class MainWindow.
 *
 * @author Markus Haecker
 * @date 2010-04-14
 *
 * @todo Check support for (german) special chars after I18n implementation.
 */

#include "MainWindow.h"
#include "OffScene.h"

/**
 * Constructor of class MainWindow.
 * The class is derived from the base class QMainWindow (public).
 * The layout has been created with Qt Designer and is loaded from file MainWindow.ui.
 *
 * @param[in] parent Parent widget (default = 0).
 */
MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
{
	ui.setupUi(this);

	scene = 0;
	glWidget = new GlWidget();
	setCentralWidget(glWidget);

	showMenuRenderModes();

	statusBar()->showMessage(tr("Welcome"));

	connectSignalsAndSlots();
}

/**
 * Destructor of MainWindow.
 */
MainWindow::~MainWindow()
{
	delete renderModesAlignmentGroup;

	for (int i = 0; i < actionRenderMode.size(); ++i) {
		delete actionRenderMode.at(i);
	}
}

/**
 * This is just a temporary method that prompts a MessageBox while calling an
 * unimplemented menu item.
 */
void MainWindow::notYet()
{
	QMessageBox::information(this, tr("Not yet implemented..."),
			tr("That's something we have to work on."));
}

/**
 * Assign menu items (generated from MainWindow.ui) to functions (slots).
 * Menu items for choosing a render mode are generated by showMenuRenderModes().
 */
void MainWindow::connectSignalsAndSlots()
{
    connect(ui.actionOpen_File,	SIGNAL(triggered()), this, SLOT(open()));
    connect(ui.actionClose_File, SIGNAL(triggered()), this, SLOT(close()));
    connect(ui.actionExit, SIGNAL(triggered()), this, SLOT(exit()));
    connect(ui.actionXz_Plane, SIGNAL(triggered()), this, SLOT(notYet()));
    connect(ui.actionXy_Plane, SIGNAL(triggered()), this, SLOT(notYet()));
    connect(ui.actionYz_Plane, SIGNAL(triggered()), this, SLOT(notYet()));
    connect(ui.actionChoose_Background_Color, SIGNAL(triggered()), this,
			SLOT(setBackgroundColor()));
    connect(ui.actionChoose_Object_Color, SIGNAL(triggered()), this,
			SLOT(setObjectColor()));
    connect(ui.actionShow_Coordinate_System, SIGNAL(toggled(bool)), this,
			SLOT(notYet()));
    connect(ui.actionReset_View, SIGNAL(triggered()), this, SLOT(notYet()));
    connect(ui.actionGerman, SIGNAL(triggered()), this, SLOT(notYet()));
    connect(ui.actionEnglish, SIGNAL(triggered()), this, SLOT(notYet()));
    connect(ui.actionHelp_Content, SIGNAL(triggered()), this, SLOT(notYet()));
    connect(ui.actionAbout_OffView, SIGNAL(triggered()), this, SLOT(about()));
    connect(ui.actionAbout_Qt, SIGNAL(triggered()), this, SLOT(aboutQt()));
}

/**
 * Display all available render modes in menu "View" -> "Mode".
 * The render modes are provided in a QStringList by listRenderModes().
 * Render modes are shown in an alignment group, each one with a radio button,
 * so that only one mode can be marked as active.
 * Render mode items are connected with setRenderMode(), which is competent
 * to initiate the mode change.
 */
void MainWindow::showMenuRenderModes()
{
	QStringList nameOfRenderModes = glWidget->listRenderModes();

	int numberOfRenderModes = nameOfRenderModes.size();
	renderModesAlignmentGroup = new QActionGroup(this);

	for (int i = 0; i < numberOfRenderModes; ++i) {
		actionRenderMode.append(new QAction(
				tr(nameOfRenderModes.at(i).toLocal8Bit().constData()), this));
		actionRenderMode[i]->setCheckable(true);
		connect(actionRenderMode[i], SIGNAL(toggled(bool)), this, SLOT(setRenderMode()));

		renderModesAlignmentGroup->addAction(actionRenderMode[i]);
		ui.menuMode->addAction(actionRenderMode[i]);
	}

	int renderMode = glWidget->renderMode();
	actionRenderMode[renderMode]->setChecked(true); // Mark radio button of active mode
}

/**
 * Shows an "Open File" dialog.
 * Users can select an *.off file. After clicking "open" it is attempted to open
 * and parse the file and show the 3D model in the window.
 */
void MainWindow::open()
{
	QString file = QFileDialog::getOpenFileName(
	         this, tr("Open File"),
	         QDir::homePath(), tr("Off Files (*.off)"));

	if(!file.isNull()) {

		try {
			glWidget->setScene(0);
			if (scene) {
				delete scene;
			}
			scene = new OffScene(file);
			glWidget->setScene(scene);
		}

		catch (...) {
			// As soon as the parser will throw exceptions, I will
			// catch them here...
		}
	}

}

/**
 * Clear the window, vanishs any 3D model shown in it.
 */
void MainWindow::close()
{
	glWidget->setScene(0);
	if (scene)
		delete scene;
	scene = 0;
}

/**
 * Tells the application to exit.
 */
void MainWindow::exit()
{
	QApplication::exit();
}

/**
 * Coming soon...
 */
void MainWindow::setBackgroundColor()
{
	notYet();
}

/**
 * Coming soon...
 */
void MainWindow::setObjectColor()
{
//	QColor color;
//	color = QColorDialog::getColor(QColor(255, 255, 255),
//			this, tr("Choose Object Color"));
	notYet();
}

/**
 * Set new render mode.
 * In the menu bar there is a dynamically generated menu for changing the
 * render mode. Available render modes are shown as radio buttons. If the user
 * select one, this function checks which it was and update the window.
 *
 * @see void GlWidget::setRenderMode(int)
 */
void MainWindow::setRenderMode()
{
	for (int i = 0; i < actionRenderMode.size(); ++i) {
		if (actionRenderMode.at(i)->isChecked()) {
			glWidget->setRenderMode(i);
			break;
		}
	}
	statusBar()->showMessage(glWidget->renderModeName() + tr(" activated"));
}

/**
 * Displays a simple message box about our cool viewer...
 */
void MainWindow::about()
{
	QString body = "<h3>About OffView</h3>"
			"<p>This program is for viewing Object File Format (.off) files in 3D "
			"with OpenGL.</p>"
			"<p>Object File Format files are used to represent the geometry of a "
			"model by specifying the polygons of the model's surface. The "
			"polygons can have any number of vertices.</p>"
			"<p>OffView is written by four students of software engineering at "
			"Konstanz University of Applied Sciences, Germany:</p>"
			"<ul>"
			"<li>Manuel Caputo,</li>"
			"<li>Markus Haecker,</li>"
			"<li>Daniel Fritz and</li>"
			"<li>Benjamin Stauder.</li>"
			"</ul>"
			"<p>The project is hosted on Google Code and can be found under "
			"<a href=\"http://code.google.com/p/offview/\">http://code.google.com/p/offview</a>. "
			"It's free software under the conditions of version 3 of the GNU General "
			"Public License (<a href=\"http://www.gnu.org/licenses/gpl-3.0.html\">GPLv3</a>). "
			"</p>";

	QMessageBox::about(this, "About OffView", body);
}

/**
 * Displays a simple message box about Qt. The message includes the version
 * number of Qt being used by the application.
 */
void MainWindow::aboutQt()
{
	QApplication::aboutQt();
}
